package affcom;

import java.awt.*;
import java.awt.event.*;
import javax.swing.JPanel;

public class TThumb extends Panel implements Adjustable, MouseListener
{
    private  static final int  mini = 12;  // Space for mini-buttons
    private int                ndig;  // Number of digits
    private TNixie            disp;  // Nixie display
    private Insets             iset;  // Insets
    private AdjustmentListener list;  // Adjustment listeners
    private Color editTint = Color.green;
    private Color affTint = Color.yellow;
    private boolean edit = true;

//-----------------------------------------------------
/**
 * Constructor, default color, 1 digit
 */
    public TThumb()
    {
	this(Color.green, 1, null);

    }
//-----------------------------------------------------
/**
 * Constructor
 * default color
 * @param nd : number of digits
 */

    public TThumb(int nd)
    {
	this(Color.green, nd, null);
    }
//-----------------------------------------------------

/**
 * Constructor
 * @param co :1st argument is display color
 * @param nd :2nd argument is number of digits
 */

    public TThumb(Color co, int nd)
    {
	this(co, nd, null);
    }

//-----------------------------------------------------

// Constructor, with listener
// 1st argument is display color
// 2nd argument is number of digits
// 3rd argument is listener for adjustments
    public TThumb(Color co, int nd, AdjustmentListener al)
    {
	super(new TCells());
	iset = new Insets(mini, 0, mini, 0);
	ndig = Math.max(Math.abs(nd), 1);
	disp = new TNixie(co, ndig);
	addMouseListener(this);
	if (al != null) addAdjustmentListener(al);
	add(disp, null); //"A1");
	setValu(0);
    }

    public void setEdit(boolean on)
    {
	edit = on;
	disp.setTint(on? editTint:affTint);
    }
    public boolean isEdit()
    {
	return edit;
    }

    public void setAffTint(Color co)
    {
	affTint = co;
	disp.setTint(edit? editTint:affTint);
    }

    public Color getAffTint()
    {
	return affTint;
    }

    public void setEditTint(Color co)
    {
	editTint = co;
	disp.setTint(edit? editTint:affTint);
    }

    public Color getEditTint()
    {
	return editTint;
    }
//-----------------------------------------------------
//-----------------------------------------------------

// Increments the counter
    public void addValu()
    {
	setValu(getValu() + 1);
    }

//-----------------------------------------------------

// Increments the counter
// 1st argument is an increment
    public void addValu(int iv)
    {
	setValu(getValu() + iv);
    }

//-----------------------------------------------------

// Required by Adjustable interface
// Returns block increment
    public int getBlockIncrement()
    {
	return 1;
    }

//-----------------------------------------------------

// Ensures space for border
    public Insets getInsets()
    {
	return iset;
    }

//-----------------------------------------------------

// Required by Adjustable interface
// Returns maximum value
    public int getMaximum()
    {
	return (int)(Math.pow(10., (double)ndig) - .9);
    }

//-----------------------------------------------------

// Required by Adjustable interface
// Returns minimum value
    public int getMinimum()
    {
	return 0;
    }

//-----------------------------------------------------

// Required by Adjustable interface
// Returns orientation
    public int getOrientation()
    {
	return Adjustable.VERTICAL;
    }

//-----------------------------------------------------


// Required by Adjustable interface
// Returns the unit increment
    public int getUnitIncrement()
    {
	return 1;
    }

//-----------------------------------------------------

// Returns value of digits
    public int getValu()
    {
	return (int)(disp.getValu() + 0.1);
    }

//-----------------------------------------------------

// Required by Adjustable interface
// Returns value
    public int getValue()
    {
	return getValu();
    }

//-----------------------------------------------------

// Required by Adjustable interface
// Returns visible amount
    public int getVisibleAmount()
    {
	return 1;
    }

//-----------------------------------------------------

// Mouse event handler
    public void mouseClicked (MouseEvent ev)
    {
	if (edit)
	{
	    if (ev.getClickCount() == 0) return;
	    Dimension sz = disp.getPreferredSize();
	    int wc =  sz.width ;
	    int hc =  sz.height;
	    sz = getSize();
	    int x1 = (sz.width  - wc) / 2 + 3;
	    int y1 = (sz.height - hc) / 2 - mini;
	    int x2 = x1 + wc   - 6;
	    int y2 = y1 + mini - 2;
	    int y3 = y2 + hc   + 3;
	    int y4 = y3 + mini - 2;
	    int xp = ev.getX();
	    if (xp < x1 || xp > x2) return;
	    int yp = ev.getY();
	    if (yp < y1 || yp > y4) return;
	    if (yp > y2 && yp < y3) return;
	    wc = (x2 + 1 - x1) / ndig;
	    x1 = (xp     - x1) / wc  ;
	    String st = disp.getText();
	    x2 = st.charAt(x1) - '0';
	    if (yp > y2){
		x2 = (x2 + 9) % 10;
		y1 = AdjustmentEvent.UNIT_DECREMENT;
	    }
	    else {
		x2 = (x2 + 1) % 10;
		y1 = AdjustmentEvent.UNIT_INCREMENT;
	    }
	    st = st.substring( 0, x1) + x2 +
		 st.substring(x1 + 1);
	    disp.setText(st);
	    // Broadcast an adjustment event
	    if (list == null) return;
	    list.adjustmentValueChanged(new AdjustmentEvent(
		    this, AdjustmentEvent.ADJUSTMENT_VALUE_CHANGED,
		    y1, getValu()));
	}
    }
    public void mouseEntered (MouseEvent ev) {}
    public void mouseExited  (MouseEvent ev) {}
    public void mousePressed (MouseEvent ev) {}
    public void mouseReleased(MouseEvent ev) {}

//-----------------------------------------------------

// Draws thumbwheels
    public void paint(Graphics gr)
    {
	super.paint(gr);
	Dimension sz = disp.getPreferredSize();
	int wc =  sz.width ;
	int hc =  sz.height;
	sz = getSize();
	int x1 = (sz.width  - wc) / 2 + 3;
	int y1 = (sz.height - hc) / 2 - mini;
	int y2 =  y1 + 1    + hc      + mini;
	wc = wc   - 6;
	hc = mini - 1;
	gr.setColor(Color.black);
	gr.fillRect(x1, y1, wc, hc);
	gr.fillRect(x1, y2, wc, hc);
	gr.setColor(getBackground());
	x1 = x1 + 1;
	y1 = y1 + 1;
	y2 = y2 + 1;
	wc = wc / ndig - 3;
	hc =      mini - 4;
	for (int i = 0; i < ndig; i = i + 1) {
	    gr.draw3DRect(x1, y1, wc, hc, true);
	    gr.draw3DRect(x1, y2, wc, hc, true);
	    x1 = x1 + 1;
	    gr.fillRect(x1, y1 + 1, wc - 1, hc - 1);
	    gr.fillRect(x1, y2 + 1, wc - 1, hc - 1);
	    x1 = x1 + 2 + wc;
	}
    }

//-----------------------------------------------------
// Adds an adjustment listener
// 1st argument is the listener
    public synchronized void addAdjustmentListener(AdjustmentListener al)
    {
	list = AWTEventMulticaster.add(list, al);
    }

// Removes an adjustment listener
// 1st argument is the listener
    public synchronized void removeAdjustmentListener(AdjustmentListener al)
    {
	list = AWTEventMulticaster.remove(list, al);
    }

//-----------------------------------------------------

// Required by Adjustable interface
// Sets block increment
    public void setBlockIncrement(int iv) {}

//-----------------------------------------------------

// Required by Adjustable interface
// Sets maximum value
    public void setMaximum(int mv) {}

//-----------------------------------------------------

// Required by Adjustable interface
// Sets minimum value
    public void setMinimum(int mv) {}

//-----------------------------------------------------



// Required by Adjustable interface
// Sets unit increment
    public void setUnitIncrement(int iv) {}

//-----------------------------------------------------

// Updates the counter
// 1st argument is the required value
    public void setValu(int iv)
    {
	int av = Math.abs(iv);
	String st = "";
	for (int i = 0; i < ndig; i = i + 1) {
	    st = (av % 10) + st;
	    av =  av / 10;
	}
	disp.setText(st);
    }

//-----------------------------------------------------

// Required by Adjustable interface
// Sets value
    public void setValue(int iv)
    {
	setValu(iv);
    }

//-----------------------------------------------------

// Required by Adjustable interface
// Sets visible amount
    public void setVisibleAmount(int iv) {}

//-----------------------------------------------------

// Decrements the counter
    public void subValu() {
	setValu(getValu() - 1);
    }

//-----------------------------------------------------

// Decrements the counter
// 1st argument is a decrement
    public void subValu(int iv) {
	setValu(getValu() - iv);
    }

//-----------------------------------------------------
    public void setText(String s)
    {
	disp.setText(s);
    }
    public String getText()
    {
	return disp.getText();
    }

}